import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';

import { BsModalService } from '@farris/ui-modal';
import { Observable, of, Subject } from 'rxjs';
import { IdService } from '@farris/ui-common';
import { switchMap } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { NotifyService } from '@farris/ui-notify';
import { LoadingService } from '@farris/ui-loading';
import { FormComponentType, FormSchemaEntity, FormViewModel, DomService, FormBasicService, DesignerEnvType } from '@farris/designer-services';
import { ControlService } from '../../../../../service/control.service';
import { DgControl } from '../../../../../utils/dg-control';
import { ComponentCreatorService } from '@farris/designer-devkit';
import { AppNavigationBeComponent } from '@farris/app-navigation-be';
import { FarrisMetadataService } from '@farris/designer-services';
const ROOT_VIEW_MODEL_ID = 'root-viewmodel';

/**
 * 多视图容器管理类
 */
@Injectable({
  providedIn: 'root'
}
)
export class MultiViewManageService {
  /** 支持的视图类型 */
  viewTypeOptions = [];

  /** 视图项绑定的数据源 */
  dataSource: string;

  /** 主表实体label */
  mainEntityLabel = '';

  /** 视图项绑定的数据源信息 */
  bindEntityInfo: { id: string, code: string, name: string, bindTo: string };

  /** 临时记录要追加的组件，在窗口点击确定时再向DOM中添加 */
  createdComponent = {};

  /** 新加的交叉表视图id集合---用于追加交叉表视图后，保存表单时向VO元数据追加查询相关动作 */
  newCrosstabViewIds = [];

  constructor(
    private controlService: ControlService,
    private domService: DomService,
    private resolver: ComponentFactoryResolver,
    private modalService: BsModalService,
    private injector: Injector,
    private formBasicService: FormBasicService,
    private idService: IdService,
    private metadataService: FarrisMetadataService,
    private http: HttpClient,
    private notifyService: NotifyService,
    private loadingService: LoadingService) { }


  initViewTypes(dataSource: string, currentViewItems?: any[]) {

    this.dataSource = dataSource;
    const schemas = this.domService.getSchemas();
    this.bindEntityInfo = this.getEntityInfoDataSource(schemas.entities);

    if (this.formBasicService.envType === DesignerEnvType.noCode) {
      this.viewTypeOptions = [
        { id: 'EmptyView', name: '空视图' },
        { id: 'ListView', name: 'ListView视图' },
        { id: 'SplitView', name: '分屏视图' },
      ];
    } else {
      this.viewTypeOptions = [
        { id: 'EmptyView', name: '空视图' },
        { id: 'ListView', name: 'ListView视图' },
        { id: 'SplitView', name: '分屏视图' },
        // { id: 'ChartView', name: '图表视图' },
        // { id: 'CrosstabView', name: '交叉表视图' }
      ];
    }
    // 目前只支持添加一个预约日历视图
    if (currentViewItems && !currentViewItems.find(item => item.viewType === 'AppointmentCalendar')) {
      this.viewTypeOptions.push({ id: 'AppointmentCalendar', name: '预约日历视图' });
    }

    // 从表不支持分屏视图、图表视图、交叉表视图
    if (this.bindEntityInfo.bindTo !== '/') {
      this.viewTypeOptions = [
        { id: 'EmptyView', name: '空' },
        { id: 'ListView', name: 'ListView视图' }
      ];
    }

    this.createdComponent = {};
  }


  createMultiViewItem(viewType: string, currentViewItems?: any[]) {
    const subject = new Subject<any>();

    let viewItem;
    const radomNum = Math.random().toString().slice(2, 6);
    const multiViewClass = this.bindEntityInfo.bindTo === '/' ?
      'f-viewchange-content-item f-utils-fill-flex-column' : 'f-viewchange-content-item';

    // 新增视图
    viewItem = this.controlService.getControlMetaData('MultiViewItem');
    viewItem.id = 'viewItem_' + radomNum;
    viewItem.title = '视图_' + radomNum;
    viewItem.icon = 'f-icon f-icon-group';
    viewItem.appearance = viewItem.appearance || {};
    viewItem.appearance.class = multiViewClass;

    switch (viewType) {
      case 'ListView': {
        viewItem.title = 'ListView视图_' + radomNum;
        viewItem.icon = 'f-icon f-icon-list_view';

        const compRefNode = this.createListViewComponent(radomNum);
        viewItem.contents = [compRefNode];
        viewItem.viewType = 'ListView';

        return of(viewItem);
      }
      case 'SplitView': {
        viewItem.title = '分屏视图_' + radomNum;
        viewItem.icon = 'f-icon f-icon-perspective_view';

        const contentContainer = this.createGridSplitMultiView(radomNum);
        viewItem.contents = [contentContainer];
        viewItem.viewType = 'SplitView';

        return of(viewItem);
      }
      // case 'ChartView': {
      //   viewItem.title = '图表视图_' + radomNum;
      //   viewItem.icon = 'f-icon f-icon-chart_view';

      //   this.showSelectQoModal(radomNum, 'ChartView').subscribe(chartsMetadata => {
      //     if (chartsMetadata) {
      //       viewItem.contents = [chartsMetadata];
      //       viewItem.viewType = 'ChartView';

      //       subject.next(viewItem);
      //     }
      //   });
      //   break;

      // }
      // case 'CrosstabView': {
      //   viewItem.title = '交叉表视图_' + radomNum;
      //   viewItem.icon = 'f-icon f-icon-chart_view';

      //   this.showSelectQoModal(radomNum, 'CrosstabView').subscribe(chartsMetadata => {
      //     if (chartsMetadata) {
      //       viewItem.contents = [chartsMetadata];
      //       viewItem.viewType = 'CrosstabView';

      //       this.newCrosstabViewIds.push(viewItem.id);

      //       subject.next(viewItem);

      //     }
      //   });
      //   break;

      // }
      case 'AppointmentCalendar': {
        // 目前只支持添加一个日历视图
        if (currentViewItems && currentViewItems.find(item => item.viewType === 'AppointmentCalendar')) {
          return of(null);
        }
        viewItem.title = '预约日历视图_' + radomNum;
        viewItem.icon = 'f-icon f-icon-calendar';

        const compRefNode = this.createAppointmentCalendarComponent(radomNum);
        viewItem.contents = [compRefNode];
        viewItem.viewType = 'AppointmentCalendar';

        return of(viewItem);
      }
      default: {
        return of(viewItem);
      }
    }

    return subject;
  }

  private createListViewComponent(radomNum: string) {

    const dataSource = this.dataSource;
    const listViewViewModel = new FormViewModel();
    Object.assign(listViewViewModel, {
      id: `${dataSource}-${radomNum}-component-viewmodel`,
      code: `${dataSource}-${radomNum}-component-viewmodel`,
      name: this.bindEntityInfo.name,
      bindTo: this.bindEntityInfo.bindTo,
      parent: ROOT_VIEW_MODEL_ID,
      fields: [],
      commands: [],
      states: [],
      enableValidation: true,
      pagination: {
        enable: false
      }
    });


    const listViewComponent = this.controlService.getControlMetaData(DgControl.Component.type);
    const listViewElement = this.controlService.getControlMetaData(DgControl.ListView.type);


    Object.assign(listViewComponent, {
      id: `${dataSource}-${radomNum}-component`,
      viewModel: listViewViewModel.id,
      componentType: FormComponentType.listView,
      appearance: {
        class: this.bindEntityInfo.bindTo === '/' ? 'f-utils-fill-flex-column' : 'f-grid-is-sub f-utils-flex-column'
      },
      contents: [listViewElement]
    });
    Object.assign(listViewElement, {
      id: `${dataSource}-${radomNum}-listview`,
      appearance: {
        class: this.bindEntityInfo.bindTo === '/' ? 'f-section' : ''
      },
      fill: true
    });


    const listViewComponentRef = this.controlService.getControlMetaData(DgControl.ComponentRef.type);

    Object.assign(listViewComponentRef, {
      id: `${dataSource}-${radomNum}-component-ref`,
      component: listViewComponent.id
    });

    this.createdComponent[listViewComponent.id] = {
      component: listViewComponent,
      viewModel: listViewViewModel
    };
    return listViewComponentRef;
  }

  private createAppointmentCalendarComponent(radomNum: string) {

    const componentCreatorService = new ComponentCreatorService(null, this.domService, this.injector);
    componentCreatorService.controlService = this.controlService;
    const buildInfo = {
      componentIdPrefix: `${this.dataSource}-${radomNum}-component`,
      resolvedComponentType: FormComponentType.appointmentCalendar,
      componentType: 'AppointmentCalendar',
      // componentAppearance: 'f-struct-wrapper f-utils-fill-flex-column',
      componentName: this.bindEntityInfo.name,
      bindTo: this.bindEntityInfo.bindTo,
      selectedFields: [],
      componentId: `${this.dataSource}-${radomNum}`,
      dataSource: this.dataSource
    };
    const componentRefNode = componentCreatorService.createComponentRefNode(buildInfo);

    const componentNode = componentCreatorService.createComponentNode(buildInfo);

    const viewModelNode = componentCreatorService.createViewModeNode(buildInfo);

    this.createdComponent[componentNode.id] = {
      component: componentNode,
      viewModel: viewModelNode
    };
    return componentRefNode;
  }

  /**
   * 创建左边ListView ， 右边外部组件的容器
   * @param radomNum 随机码
   */
  private createGridSplitMultiView(radomNum: string): any {

    // 1、创建ListView组件
    const listViewComponentRef = this.createListViewComponent(radomNum);

    // 创建父容器
    const listViewParentContainer = this.controlService.getControlMetaData(DgControl.ContentContainer.type);
    Object.assign(listViewParentContainer, {
      id: `splitview-container-${radomNum}`,
      appearance: {
        class: 'f-utils-fill d-flex'
      },
      contents: [
        listViewComponentRef,
        {
          id: `right-container-${radomNum}`,
          type: 'ContentContainer',
          appearance: {
            class: 'f-col-w8'
          },
          visible: true,
          isScrollspyContainer: false,
          draggable: false,
          contents: [
            {
              id: `external-container-${radomNum}`,
              type: 'ExternalContainer'
            }
          ]
        }
      ]
    });

    return listViewParentContainer;

  }

  /**
   * 移除记录的追加组件
   * @param selecteItem 选中的视图节点
   */
  removeItem(selecteItem: any) {

    const addedComponentIds = Object.keys(this.createdComponent);

    const addedCmp = this.domService.selectNode(selecteItem, item => {
      return item.type === DgControl.ComponentRef.type && addedComponentIds.includes(item.component);
    });
    if (addedCmp) {
      delete this.createdComponent[addedCmp.component];
    }
  }

  /**
   * 图表类视图，弹出选择QO的窗口
   */
  // showSelectQoModal(randomNum: string, viewType: string): Observable<any> {
  //   const subject = new Subject<any>();
  //   const compFactory = this.resolver.resolveComponentFactory(AppNavigationBeComponent);
  //   const compRef = compFactory.create(this.injector);

  //   // 配置模态框参数
  //   compRef.instance.editorParams = {
  //     // 路径
  //     relativePath: this.formBasicService.formMetaBasicInfo.relativePath || "",
  //     range: 'Bo',
  //     source: 'qo',
  //   }
  //   // 配置模态框参数
  //   const modalConfig = {
  //     title: '选择查询对象',
  //     width: 900,
  //     height: 500,
  //     resizable: true,
  //     showButtons: false,
  //     showMaxButton: false,
  //     minWidth: 650,
  //     minHeight: 300,
  //   }
  //   // compRef.instance.onlyDisplayCurrentProject = false;
  //   const dialog = this.modalService.show(compRef, modalConfig);

  //   // 关闭
  //   compRef.instance.closeModal.subscribe((data) => {
  //     subject.next();
  //     dialog.close();
  //   });
  //   // 选定元数据
  //   compRef.instance.submitModal.subscribe(data => {
  //     switch (viewType) {
  //       case 'ChartView': {
  //         this.createChartsView(data, randomNum).subscribe(chartsMetadata => {
  //           subject.next(chartsMetadata);
  //         });
  //         break;
  //       }
  //       case 'CrosstabView': {
  //         this.createCrosstabView(data, randomNum).subscribe(crosstabMetadata => {
  //           subject.next(crosstabMetadata);
  //         });
  //         break;
  //       }
  //     }
  //     dialog.close();
  //   });
  //   return subject;
  // }

  // /**
  //  * 创建图表视图：QdpFramework--Charts控件
  //  * @param $event 选择的qo元数据
  //  * @param radomNum 随机码
  //  */
  // private createChartsView($event: any, radomNum: string) {
  //   if (!$event) {
  //     return of(null);
  //   }
  //   const subject = new Subject<string>();

  //   const qdpFrameworkMetadata = this.controlService.getControlMetaData(DgControl.QdpFramework.type);
  //   const chartsMetadata = this.controlService.getControlMetaData(DgControl.Charts.type);

  //   const qoManagerCode = ('com.' + $event.metadata.nameSpace + '.' + $event.metadata.code || '').toLowerCase();
  //   const voSourceUri = this.domService.getSchemas().sourceUri.toLowerCase();
  //   const voMetadataId = this.domService.getSchemas().id;
  //   const voCode = this.domService.getSchemas().code;


  //   this.getVoJavaConfigId(voMetadataId, voCode).subscribe(voConfigId => {
  //     const queryId = this.idService.generate();
  //     Object.assign(chartsMetadata, {
  //       id: `charts-${radomNum}`,
  //       appearance: {
  //         class: 'd-flex flex-fill'
  //       },
  //       queryId,
  //       controlType: 'charts',
  //       chartsDataSource: 'lcp',
  //       qoManagerCode,
  //       voId: voConfigId
  //     });

  //     Object.assign(qdpFrameworkMetadata, {
  //       id: `qdp-framework-${radomNum}`,
  //       appearance: {
  //         class: 'f-page-main position-relative m-0'
  //       },
  //       queryId,
  //       qoManagerCode,
  //       controlType: 'charts',
  //       queryRelativeUrl: `/${voSourceUri}/service/`,
  //       qoId: $event.metadata.id,
  //       voId: voConfigId,
  //       templateType: 'none',
  //       contents: [chartsMetadata]
  //     });

  //     subject.next(qdpFrameworkMetadata);
  //   });


  //   return subject;
  // }

  // /**
  //  * 创建交叉表视图：QdpFramework--Spreadsheet控件
  //  * @param $event 选择的qo元数据
  //  * @param radomNum 随机码
  //  */
  // createCrosstabView($event: any, radomNum: string) {
  //   if (!$event) {
  //     return of(null);
  //   }
  //   const subject = new Subject<string>();

  //   const qdpFrameworkMetadata = this.controlService.getControlMetaData(DgControl.QdpFramework.type);
  //   const spreadSheetMetadata = this.controlService.getControlMetaData(DgControl.SpreadSheet.type);

  //   const qoManagerCode = ('com.' + $event.metadata.nameSpace + '.' + $event.metadata.code || '').toLowerCase();
  //   const voSourceUri = this.domService.getSchemas().sourceUri.toLowerCase();


  //   const voMetadataId = this.domService.getSchemas().id;
  //   const voCode = this.domService.getSchemas().code;

  //   this.getVoJavaConfigId(voMetadataId, voCode).subscribe(voConfigId => {

  //     const queryId = this.idService.generate();
  //     Object.assign(spreadSheetMetadata, {
  //       id: `spreadSheet-${radomNum}`,
  //       appearance: {
  //         class: 'd-flex flex-fill'
  //       },
  //       queryId,
  //       controlType: 'crosstab',
  //       qoManagerCode,
  //       qoId: $event.metadata.id,
  //       voId: voConfigId,
  //       queryRelativeUrl: `/${voSourceUri}/service/`,
  //       templateType: 'none'
  //     });

  //     Object.assign(qdpFrameworkMetadata, {
  //       id: `qdp-framework-${radomNum}`,
  //       appearance: {
  //         class: 'f-page-main position-relative m-0'
  //       },
  //       queryId,
  //       qoManagerCode,
  //       controlType: 'crosstab',
  //       queryRelativeUrl: `/${voSourceUri}/service/`,
  //       qoId: $event.metadata.id,
  //       voId: voConfigId,
  //       templateType: 'none',
  //       contents: [spreadSheetMetadata]
  //     });

  //     subject.next(qdpFrameworkMetadata);

  //   });


  //   return subject;
  // }

  // /**
  //  * 获取VO元数据配置的java configId，不能直接按照表单的nameSpace拼接。
  //  */
  // getVoJavaConfigId(voMetadataId: string, voCode: string) {
  //   let voConfigId = '';
  //   const subject = new Subject<string>();
  //   let ob: Observable<any> = this.metadataService.getMetadata(voMetadataId);

  //   if (ob) {
  //     ob.subscribe(voData => {
  //       const voMetadataContent = JSON.parse(voData.content);
  //       if (voMetadataContent && voMetadataContent.GeneratingAssembly) {
  //         voConfigId = 'com.' + voMetadataContent.GeneratingAssembly.toLowerCase() + '.' + voCode;
  //       }
  //       subject.next(voConfigId);
  //     }, () => {
  //       this.notifyService.error('获取VO元数据失败！');
  //     });
  //   }
  //   return subject;
  // }


  // /**
  //  * 多视图添加交叉表视图场景：安装qdp相关maven包；向VO元数据追加交叉表查询相关的动作（暂不同步eapi）
  //  */
  // addVOActionsForCrosstabView() {
  //   if (this.formBasicService.envType !== DesignerEnvType.designer) {
  //     // console.log('运行时定制表单暂不支持向vo追加查询动作！');
  //     return;
  //   }
  //   if (this.newCrosstabViewIds.length === 0) {
  //     return;
  //   }
  //   const loading = this.loadingService.show({ container: 'body', message: '正在添加查询相关动作，请稍候...' });
  //   const sessionId = '';
  //   const formMetadataPath = this.formBasicService.formMetaBasicInfo.relativePath;

  //   const voMetadataId = this.domService.getSchemas().id;
  //   const vmfilename = this.domService.getSchemas().code + '.vo';

  //   const headerOptions = {
  //     headers: new HttpHeaders({ 'Content-Type': 'text/json', SessionId: '' })
  //   };

  //   this.checkAndRestoreMetadataPackages().pipe(
  //     switchMap(() => {
  //       return this.metadataService.GetRefMetadata(formMetadataPath, voMetadataId, sessionId);
  //     }),
  //     switchMap((voData) => {
  //       const voMetadataPath = voData.relativePath;

  //       const body = {
  //         vmfilename,
  //         vmpath: voMetadataPath
  //       };
  //       return this.http.put(`/api/dev/main/v1.0/qometadata/updateviewmodelwithqdpcmp`, body, headerOptions);
  //     })
  //   ).subscribe(() => {
  //     this.newCrosstabViewIds = [];
  //     loading.close();
  //     this.notifyService.success('添加成功');
  //   }, () => {
  //     this.notifyService.error('添加查询相关动作失败');
  //     loading.close();
  //   });

  // }

  // /**
  //  * 安装qdp元数据包
  //  * @param packageNames 待安装的元数据包
  //  */
  // checkAndRestoreMetadataPackages() {
  //   const qdpMetadataPackages = 'Inspur.GS.Gsp.QDP.QdpCmp.mdpkg,Inspur.GS.Gsp.QDP.QdpCommonCmp.mdpkg,Inspur.Gsp.Common.CommonCmp.mdpkg';
  //   const formMetadataPath = this.formBasicService.formMetaBasicInfo.relativePath;

  //   let projPath: string;
  //   return this.metadataService.GetProjPath(formMetadataPath).pipe(
  //     switchMap(path => {
  //       projPath = path;
  //       return this.metadataService.getMavenStatus(projPath);
  //     }),
  //     switchMap(isMaven => {
  //       return this.metadataService.addDependencyAndRestore(projPath, qdpMetadataPackages, isMaven);
  //     })
  //   );
  // }

  /**
   * 根据数据源dataSource，获取实体信息，以及用于viewModel的bindTo属性
   */
  private getEntityInfoDataSource(entities: FormSchemaEntity[], labelPath = ''): any {
    if (!entities || entities.length === 0) {
      return;
    }

    const parentLabelPath = labelPath;
    for (const entity of entities) {
      const entityType = entity.type;
      if (!entityType) {
        return [];
      }
      labelPath = parentLabelPath === '' ? entity.label : parentLabelPath + '/' + entity.label;
      this.mainEntityLabel = !this.mainEntityLabel ? entity.label : this.mainEntityLabel;

      if (this.dataSource === entity.label) {
        const bindTo = labelPath.replace(this.mainEntityLabel, '');
        return {
          id: entity.id,
          label: entity.label,
          name: entity.name,
          displayName: entity.type.displayName,
          bindTo: bindTo === '' ? '/' : bindTo
        };
      }
      if (entityType.entities && entityType.entities.length > 0) {
        const entityInfo = this.getEntityInfoDataSource(entityType.entities, labelPath);
        if (entityInfo) {
          return entityInfo;
        }
      }
    }
  }

  /**
   * 视图变更后，更新viewChange图标组件
   * @param latestViews 变更后的视图组
   * @param viewChangeBar 视图切换控件路径
   * @param parentContainer 多视图父容器
   * @param componentId 父容器所在的组件id
   * （TODO：页头有header容器和header组件两种可能）
   */
  updateViewChangeButtons(latestViews: any[], viewChangeBar: any, parentContainer: any, componentId: string) {

    let viewChangeElement;
    // 子表启用多视图，图标组件放在了TabPage/Section上
    if (parentContainer && parentContainer.multiViews && parentContainer.views) {
      // 若是收折后的控件树触发的操作，那么parentContainer可能不是真是的DOM节点，需要重新查找DOM节点
      const rootDom = this.domService.getComponentById(componentId);
      const parentContainerInDom = this.domService.selectNode(rootDom, item => item.id === parentContainer.id);
      viewChangeElement = parentContainerInDom.views;
    }
    // 主表启用多视图，在多视图组件上记录了图标组件的路径
    if (viewChangeBar) {
      const rootComponentJson = this.domService.getComponentById('root-component');
      viewChangeElement = this.domService.getNodeByIdPath(rootComponentJson, viewChangeBar);
    }


    if (viewChangeElement) {
      const viewChangeItems = viewChangeElement.toolbarData as any[];
      const updatedViewChangeItems = [];
      latestViews.forEach((view) => {
        const matchedViewItem = viewChangeItems.find(item => item.id === view.id);
        if (matchedViewItem) {
          matchedViewItem.title = view.title;
          matchedViewItem.iconName = view.icon;
          updatedViewChangeItems.push(matchedViewItem);
        } else {
          updatedViewChangeItems.push({
            type: view.id,
            title: view.title,
            iconName: view.icon
          });
        }
      });
      viewChangeElement.toolbarData = updatedViewChangeItems;

      if (updatedViewChangeItems.findIndex(viewItem => viewItem.type === viewChangeElement.defaultType) < 0) {
        if (updatedViewChangeItems.length) {
          viewChangeElement.defaultType = updatedViewChangeItems[0].type;
        } else {
          viewChangeElement.defaultType = '';
        }
      }
      if (updatedViewChangeItems.findIndex(viewItem => viewItem.type === viewChangeElement.currentTypeInDesignerView) < 0) {
        if (updatedViewChangeItems.length) {
          viewChangeElement.currentTypeInDesignerView = updatedViewChangeItems[0].type;
        } else {
          viewChangeElement.currentTypeInDesignerView = '';
        }
      }
    }
  }
}
